#include "pageuartconfig.h"
#include <QSerialPort>
#include <QSerialPortInfo>
#include <QHBoxLayout>
#include <QVBoxLayout>
#include <QDebug>
#include "configmanager.h"
#include "portmanager.h"

PageUartConfig::PageUartConfig(QWidget *parent)
    : QWidget (parent)
{
    qDebug() << "PageUartConfig...";

    // widget
    setWindowTitle(tr("Uart Config"));
    setAttribute(Qt::WA_DeleteOnClose, true);

    // controls
    lbPort = new QLabel();
    lbPort->setText(tr("Port"));
    cbPort = new QComboBox();
    findPortManagerPorts();
    connect(cbPort, SIGNAL(currentIndexChanged(int)), this, SLOT(onPortChanged(int)));

    lbAvailableNames = new QLabel();
    lbAvailableNames->setText(tr("AvailableNames"));
    cbAvailableNames = new QComboBox();
    lbName = new QLabel();
    lbName->setText(tr("Name"));
    leName = new QLineEdit();

    lbBaudRate = new QLabel();
    lbBaudRate->setText(tr("BaudRate"));
    cbBaudRate = new QComboBox();
    cbBaudRate->addItem("110");
    cbBaudRate->addItem("300");
    cbBaudRate->addItem("600");
    cbBaudRate->addItem("1200");
    cbBaudRate->addItem("2400");
    cbBaudRate->addItem("4800");
    cbBaudRate->addItem("9600");
    cbBaudRate->addItem("14400");
    cbBaudRate->addItem("19200");
    cbBaudRate->addItem("38400");
    cbBaudRate->addItem("56000");
    cbBaudRate->addItem("57600");
    cbBaudRate->addItem("115200");
    cbBaudRate->addItem("128000");
    cbBaudRate->addItem("230400");
    cbBaudRate->addItem("256000");
    cbBaudRate->addItem("460800");
    cbBaudRate->addItem("921600");

    lbDataBits = new QLabel(this);
    lbDataBits->setText(tr("DataBits"));
    cbDataBits = new QComboBox(this);
    QStringList strList;
    strList << "8" << "7" << "6" << "5";
    cbDataBits->addItems(strList);

    lbStopBits = new QLabel(this);
    lbStopBits->setText(tr("StopBits"));
    cbStopBits = new QComboBox(this);
    strList.clear();
    strList << "1" << "1.5" << "2";
    cbStopBits->addItems(strList);

    lbParity = new QLabel(this);
    lbParity->setText(tr("Parity"));
    cbParity = new QComboBox(this);
    strList.clear();
    strList << tr("None") << tr("Odd") << tr("Even");
    cbParity->addItems(strList);

    pbFind = new QPushButton(this);
    pbFind->setText(tr("Find"));
    pbOpen = new QPushButton(this);

    ckbAutoOpen = new QCheckBox();
    ckbAutoOpen->setText(tr("AutoOpen"));
    pbSave = new QPushButton(this);
    pbSave->setText(tr("Save"));

    // layout
    QHBoxLayout *hblPort = new QHBoxLayout();
    hblPort->addWidget(lbPort, 1);
    hblPort->addWidget(cbPort, 1);
    QHBoxLayout *hblAvalibleNames = new QHBoxLayout();
    hblAvalibleNames->addWidget(lbAvailableNames, 1);
    hblAvalibleNames->addWidget(cbAvailableNames, 1);
    QHBoxLayout *hblName = new QHBoxLayout();
    hblName->addWidget(lbName, 1);
    hblName->addWidget(leName, 1);
    QHBoxLayout *hblBaudRate = new QHBoxLayout();
    hblBaudRate->addWidget(lbBaudRate, 1);
    hblBaudRate->addWidget(cbBaudRate, 1);
    QHBoxLayout *hblDataBits = new QHBoxLayout();
    hblDataBits->addWidget(lbDataBits, 1);
    hblDataBits->addWidget(cbDataBits, 1);
    QHBoxLayout *hblStopBits = new QHBoxLayout();
    hblStopBits->addWidget(lbStopBits, 1);
    hblStopBits->addWidget(cbStopBits, 1);
    QHBoxLayout *hblParity = new QHBoxLayout();
    hblParity->addWidget(lbParity, 1);
    hblParity->addWidget(cbParity, 1);
    QHBoxLayout *hblOpen = new QHBoxLayout();
    hblOpen->addWidget(pbFind, 1);
    hblOpen->addWidget(pbOpen, 1);
    QHBoxLayout *hblAutoOpen = new QHBoxLayout();
    hblAutoOpen->addWidget(ckbAutoOpen, 1);
    hblAutoOpen->addWidget(pbSave, 1);
    QVBoxLayout *vbl = new QVBoxLayout();
    vbl->addLayout(hblPort, 1);
    vbl->addLayout(hblAvalibleNames, 1);
    vbl->addLayout(hblName, 1);
    vbl->addLayout(hblBaudRate, 1);
    vbl->addLayout(hblDataBits, 1);
    vbl->addLayout(hblStopBits, 1);
    vbl->addLayout(hblParity, 1);
    vbl->addLayout(hblOpen, 1);
    vbl->addLayout(hblAutoOpen, 1);
    setLayout(vbl);

    setSerialPort(*m_ports.at(0));

    findAvaliblePorts();
//    connect(cbAvalibleNames, SIGNAL(currentIndexChanged(int)), this, SLOT(onAvalibleNameChanged(int)));

    //
    connect(pbFind, &QPushButton::clicked, this, [=](bool checked){
        Q_UNUSED(checked);
        findAvaliblePorts();
    });
    connect(pbOpen, &QPushButton::clicked, this, [=](){
        if (pbOpen->text() == tr("Open"))
        {
            SerialPortSetting setting;
            setting.name = leName->text();
            setting.baudRate = cbBaudRate->currentText().toInt();
            setting.dataBits = SerialPort::toDataBit(cbDataBits->currentText());
            setting.stopBits = SerialPort::toStopBit(cbStopBits->currentText());
            setting.parity = SerialPort::toParityBit(cbParity->currentText());
            setting.isAutoOpen = ckbAutoOpen->isChecked();
            QVariant var;
            var.setValue(setting);
            m_port->setConfig(var);

            m_port->openSync(1000);
            if (!m_port->isOpen())
            {
                emit error(m_port->errorString());
            }
        }
        else
        {
            m_port->closeSync(1000);
            if (m_port->isOpen())
                emit error(m_port->errorString());
        }

        checkSerialPort();
    });

    // 保存
    connect(pbSave, &QPushButton::clicked, this, [=](){
        SerialPortSetting setting;
        setting.name = leName->text();
        setting.baudRate = cbBaudRate->currentText().toInt();
        setting.dataBits = SerialPort::toDataBit(cbDataBits->currentText());
        setting.stopBits = SerialPort::toStopBit(cbStopBits->currentText());
        setting.parity = SerialPort::toParityBit(cbParity->currentText());
        setting.isAutoOpen = ckbAutoOpen->isChecked();

        portManager->saveSerialPort(m_port->getID(), setting);
    });

    bool isAutoOpen = configManager->get(CK_Uart_AutoOpen).toBool();
    ckbAutoOpen->setChecked(isAutoOpen);

    qDebug() << "PageUartConfig...completed";
}

void PageUartConfig::setSerialPort(SerialPort &port)
{
    m_port = &port;
    QVariant var = port.getConfig();
    m_setting = var.value<SerialPortSetting>();
    leName->setText(m_setting.name);
    cbBaudRate->setCurrentText(QString::number(m_setting.baudRate));
    cbDataBits->setCurrentText(SerialPort::fromDataBit(m_setting.dataBits));
    cbStopBits->setCurrentText(SerialPort::fromStopBit(m_setting.stopBits));
    cbParity->setCurrentText(SerialPort::fromParityBit(m_setting.parity));
    ckbAutoOpen->setChecked(m_setting.isAutoOpen);
    checkSerialPort();
}

void PageUartConfig::checkSerialPort()
{
    if (m_port->isOpen())
    {
        cbAvailableNames->setEnabled(false);
        leName->setEnabled(false);
        cbBaudRate->setEnabled(false);
        cbDataBits->setEnabled(false);
        cbStopBits->setEnabled(false);
        cbParity->setEnabled(false);
        pbFind->setEnabled(false);
        pbOpen->setText(tr("Close"));
    }
    else
    {
        cbAvailableNames->setEnabled(true);
        leName->setEnabled(true);
        cbBaudRate->setEnabled(true);
        cbDataBits->setEnabled(true);
        cbStopBits->setEnabled(true);
        cbParity->setEnabled(true);
        pbFind->setEnabled(true);
        pbOpen->setText(tr("Open"));
    }
}

void PageUartConfig::findAvaliblePorts(void)
{
    disconnect(cbAvailableNames, SIGNAL(currentIndexChanged(int)), this, SLOT(onAvalibleNameChanged(int)));

    cbAvailableNames->clear();

    bool isContainDefaultName = false;
    const auto infos = QSerialPortInfo::availablePorts();
    for (const QSerialPortInfo& info : infos)
    {
        //QSerialPort serial;
        //serial->setPort(info);
        //if (serial.open(QIODevice::ReadWrite))
        {
            cbAvailableNames->addItem(info.portName());
            //serial.close();
        }

        if (info.portName() == leName->text())
        {
            isContainDefaultName = true;
        }
    }
    if (!isContainDefaultName)
    {
        cbAvailableNames->insertItem(0, leName->text());
    }
    cbAvailableNames->setCurrentText(leName->text());

    connect(cbAvailableNames, SIGNAL(currentIndexChanged(int)), this, SLOT(onAvalibleNameChanged(int)));
}

void PageUartConfig::findPortManagerPorts()
{
    cbPort->clear();
    m_ports.clear();

    QList<BasePort*> ports = portManager->getAllPorts();
    foreach (BasePort *p, ports) {
        if (p->getPortType() == BasePort::PortType_Serial)
        {
            cbPort->addItem(p->getName());
            m_ports << static_cast<SerialPort*>(p);
        }
    }
}

void PageUartConfig::onPortChanged(int index)
{
    m_port = m_ports.at(index);
    QVariant var = m_port->getConfig();
    m_setting = var.value<SerialPortSetting>();

    leName->setText(m_setting.name);
    cbBaudRate->setCurrentText(QString::number(m_setting.baudRate));
    cbDataBits->setCurrentText(SerialPort::fromDataBit(m_setting.dataBits));
    cbStopBits->setCurrentText(SerialPort::fromStopBit(m_setting.stopBits));
    cbParity->setCurrentText(SerialPort::fromParityBit(m_setting.parity));
    ckbAutoOpen->setChecked(m_setting.isAutoOpen);

    checkSerialPort();

    // 先断开信号槽
    disconnect(cbAvailableNames, SIGNAL(currentIndexChanged(int)), this, SLOT(onAvalibleNameChanged(int)));
    findAvaliblePorts();
    connect(cbAvailableNames, SIGNAL(currentIndexChanged(int)), this, SLOT(onAvalibleNameChanged(int)));
}

void PageUartConfig::onAvalibleNameChanged(int index)
{
    Q_UNUSED(index);
    leName->setText(cbAvailableNames->currentText());
}
